//ProxyTest.java
package com.ylaihui.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

// 接口
interface Productor {
    public void make();
}

// 被代理类
class ApplePhone implements Productor {
    @Override
    public void make() {
        System.out.println("make phone");
    }
}

class ProductorUtil{
    public void methodComm1(){
        System.out.println("comm method 1...");
    }
    public void methodComm2(){
        System.out.println("comm method 2...");
    }
}

// 代理类动态生成
// 1. 如何根据加载到内存中的被代理类，动态的创建一个代理类及其对象。
// 2. 当通过代理类的对象调用方法a时，如何动态的去调用被代理类中的同名方法a。
class ProxyFactory {
    // object 被代理类对象
    public static Object getProxyInstance(Object object) {

        //InvocationHandler 接口的实现类实例
        ProInvocationHandler invocationHandler = new ProInvocationHandler();
        //绑定被代理类的对象，反射机制处理的时候，调用invoke(对象, 参数)，也就调用了被代理类的方法
        invocationHandler.bind(object);
        // 直接创建一个动态代理对象，并返回该对象
        return Proxy.newProxyInstance(object.getClass().getClassLoader(), object.getClass().getInterfaces(), invocationHandler);
    }
}

class ProInvocationHandler implements InvocationHandler {

    private Object obj;

    // 使用被代理类的对象进行赋值
    public void bind(Object obj) {
        this.obj = obj;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        ProductorUtil productorUtil = new ProductorUtil();

        productorUtil.methodComm1();

        // 动态调用被代理类的方法，method.invoke 方法的返回值就是 对应的被代理类方法的返回值
        Object invoke = method.invoke(obj, args);

        productorUtil.methodComm2();

        return invoke;
    }
}


public class ProxyTest {
    public static void main(String[] args) {
        ApplePhone applePhone = new ApplePhone();
        // proxyInstance 代理类的实例
        Productor proxyInstance = (Productor) ProxyFactory.getProxyInstance(applePhone);
        proxyInstance.make();

    }
}

